<?php

namespace app\uniapp\service;

use app\common\exception\MiException;
use app\common\service\CommonGoodsService;
use app\common\service\CommonOrderService;
use app\common\service\CommonSiteConfigService;
use app\common\service\CommonStoreManagerService;
use app\model\site\User;
use app\model\site\UserPointsLog;
use app\model\store\Goods;
use app\model\store\Order;
use app\model\store\OrderRefund;
use app\model\store\UserCoupon;
use app\uniapp\service\traits\InstanceTrait;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\db\Query;
use think\Exception;
use think\exception\RouteNotFoundException;
use think\facade\Db;

class OrderService extends UniBaseService
{
    use InstanceTrait;

    function initialize()
    {
        $this->model = new Order();
    }

    function formatData(array $data): array
    {
        if (isset($data['userAddress'])){
            $data['user_address'] = serialize($data['userAddress']);
            unset($data['userAddress']);
        }
        return $data;
    }

    public function query(): Query
    {
        return $this->setWith(['items', 'deliveryOrders'])
            ->makeQuery()
            ->filter(function ($v) {
                $v->userAddress = miUnserialize($v->user_address);
                $v->payTimeStr = miDate('Y-m-d H:i:s', $v->pay_time);
                $v->waitOrderRefund = OrderRefund::where('order_id', $v->id)->where('audit_status', 0)->find();
            });
    }

    /**
     * @param array $data
     * @return array
     * @throws MiException
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     *
     * 预备要创建的订单数据
     */
    function prepare(array $data): array
    {
        $orderType = $data['order_type']??'';
        $isSingle = $data['is_single']??'';
        $createType = $data['create_type']??'';  // 下单方式：购物车-cart/直接购买-goods
        $items = $data['items']??'';
        $cartIds = $data['cart_ids']??'';   // 购物车id列表
        $userAddress = $data['userAddress']??null;
        $payType = $data['pay_type']??'wx';
        $user = User::with('storeManager')->find($this->userId);

        if (!$orderType){
            throw new MiException("缺少订单类型");
        }
        if (!$createType){
            throw new MiException("缺少下单方式");
        }
        if ($createType == 'cart'){
            if (!$cartIds) throw new MiException("缺少购物车商品列表ID");
        }
        if (!$items || count($items)<1){
            throw new MiException("缺少商品");
        }
        if ($orderType == 'group'){
            if ($isSingle === ''){
                throw new MiException("拼团订单缺少下单方式，单独购买或者拼单");
            }elseif ($isSingle != 1){   // 不是单独购买
                throw new MiException("拼团订单必须指定发起人ID");
            }
        }

        // 初始化订单数据
        $order = [
            'create_type' => $createType,
            'order_type' => $orderType,
            'is_single' => $isSingle,
            'items' => [],
            'user_id' => $this->userId,
            'site_id' => $this->siteId,
            'platform' => getUniPlatform(),
            'total_price' => 0,     // 订单总金额（包含运费）
            'pay_price' => 0,       // 实际支付金额（包含运费）
            'pay_type' => $payType,
            'num' => 0,
            'points_num' => $data['points_num']??0,
            'points_price' => 0,
            'postage_price' => 0,   // 运费
            'userAddress' => $userAddress,
            'coupon_price' => 0,
            'user_coupon_id' => $data['user_coupon_id']??0,
            'isUseCoupon' => $data['isUseCoupon']??1,
            'cart_ids' => $cartIds,
            'store_manager_price' => 0,
        ];

        // 地址信息
        if (!$userAddress){ // 没有地址，设置为默认地址
            // 设置默认地址
            $order['userAddress'] = UserAddressService::instance()->getDefault();
        }

        // 当前订单中的商品所用到的运费模板信息数组。
        $postageMap = [];
        foreach($items as $v){
            $goodsId = $v['goods_id'];
            $num = (int)$v['num'];
            $skuId = $v['goods_sku_id']??0;
            if (!$num) throw new MiException("缺少商品数量");
            $goods = GoodsService::instance()->getDetailById($goodsId, $skuId);
            if (!$goods){
                throw new MiException("商品不存在");
            }
            $tplId = $goods->postage_tpl_id;
            $tpl = $goods->postageTpl;
            if (!$tpl){
                throw new MiException("运费模板不存在，商品ID:{$goods->id}");
            }

            if ($skuId){    // 多规格
                $price = (double)$goods->sku->showPrice;    // 商品价格
                $weight = (double)$goods->sku->weight;      // 重量
                $volume = (double)$goods->sku->volume;      // 体积
            }else{  // 单规格
                $price = (double)$goods->showPrice;
                $weight = (double)$goods->weight;
                $volume = (double)$goods->volume;
            }

            // 将运费模板加入数组中
            if (isset($postageMap[$tplId])){    // 已经存在当前模板，增加商品数量
                $postageMap[$tplId]['num'] += $num;
                $postageMap[$tplId]['weight'] += $weight*$num;
                $postageMap[$tplId]['volume'] += $volume*$num;
                $postageMap[$tplId]['price'] += $price*$num;
            }else{
                $postageMap[$tplId] = [
                    "tpl" => $goods->postageTpl,
                    'num' => $num,  // 使用该模板的商品的件数
                    'weight' => $weight*$num,   // 使用该模板的商品的总重量
                    'volume' => $volume*$num,   // 使用该模板的商品的总体积
                    'price' => $price*$num,     // 使用该模板的商品的总金额
                ];
            }

            // 根据商品的运费模板和用户的收货地址，判断当前商品是否支持发货
            $isExpressDelivery = PostageTemplateService::instance()->isExpressDelivery($tpl, $userAddress);

            // 订单商品数据
            $oli = [
                'goods_id' => $goodsId,
                'goods_image' => $goods->image,
                'goods_title' => $goods->title,
                'is_dist' => $goods->is_dist,
                'num' => $num,
                'price' => $price,  // 商品单价
                'pay_price' => round($price * $num,2),   // 实际支付金额
                'total_price' => round($price * $num,2), // 所有商品总金额
                'isExpressDelivery' => $isExpressDelivery,  // 是否支持发货（需要根据收货地址判断）
                'store_manager_price' => 0,
            ];

            if ($skuId){     // 多规格
                $oli['goods_sku_id'] = $skuId;
                $oli['goods_sku'] = $goods->sku->specValueStr;
            }

            $order['items'][] = $oli;

            // 订单数据
            $order['num'] += $num;
            $order['pay_price'] += $oli['pay_price'];
            $order['total_price'] += $oli['total_price'];
        }

        // 优惠券
        $storeConfig = CommonSiteConfigService::instance()->getConfigValue($this->siteId, CommonSiteConfigService::STORE);
        if ($storeConfig['is_on_coupon']==1){   // 开启了优惠券功能
            // 当前订单可用的所有优惠券
            $order['coupons'] = UserCouponService::instance()->getOrderCoupons($order);
            // 先计算优惠券抵扣
            if ($order['isUseCoupon']){ // 用户选择了使用优惠券
                $order = UserCouponService::instance()->computeOrderCouponPrice($order);
            }
        }

        // 样品基金抵扣
        if ($user->storeManager && $user->storeManager->status==1){ // 是店长 && 未禁用
            $order = CommonStoreManagerService::instance()->computeOrderStoreManagerPrice($order, $user, $user->storeManager);
        }

        // 再计算积分抵扣
        if ($order['points_num']){
            $order = UserPointsLogService::instance()->computeOrderPointsPrice($order);
        }

        // 运费
        $postagePrice = 0;
        if ($order['userAddress']){ // 存在收货地址，计算运费
            $userAddress = $order['userAddress'];
            foreach ($postageMap as $v){
                $tpl = $v['tpl'];
                $postagePrice += PostageTemplateService::instance()->getExpressPrice($tpl, $userAddress, $v['price'], $v['num'], $v['weight'], $v['volume']);
            }

        }
        $order['postage_price'] = round($postagePrice,2);
        // 在订单总金额和付款金额中加入运费
        $order['pay_price'] = round($order['pay_price'] + $postagePrice, 2);
        $order['total_price'] = round($order['total_price'] + $postagePrice, 2);

        return $order;
    }

    /**
     * 取消订单
     * @param $orderId
     * @return void
     */
    public function cancel($orderId){
        CommonOrderService::instance()->cancel($orderId, 2);
    }


}
